home *** CD-ROM | disk | FTP | other *** search
/ Aminet 31 / Aminet 31 (1999)(Schatztruhe)[!][Jun 1999].iso / Aminet / dev / c / vbccppcsrc.lha / vbcc / pasm / output_elf.c < prev    next >
C/C++ Source or Header  |  1999-03-07  |  15KB  |  461 lines

  1. /* $VER: pasm output_elf.c V1.2 (24.10.98)
  2.  *
  3.  * This file is part of pasm, a portable PowerPC assembler.
  4.  * Copyright (c) 1997-98  Frank Wille
  5.  *
  6.  * pasm is freeware and part of the portable and retargetable ANSI C
  7.  * compiler vbcc, copyright (c) 1995-98 by Volker Barthelmann.
  8.  * pasm may be freely redistributed as long as no modifications are
  9.  * made and nothing is charged for it. Non-commercial usage is allowed
  10.  * without any restrictions.
  11.  * EVERY PRODUCT OR PROGRAM DERIVED DIRECTLY FROM MY SOURCE MAY NOT BE
  12.  * SOLD COMMERCIALLY WITHOUT PERMISSION FROM THE AUTHOR.
  13.  *
  14.  *
  15.  * v1.2   (24.10.98) phx
  16.  *        An empty section with reloc symbols will no longer be deleted.
  17.  * v1.1d  (27.09.97) phx
  18.  *        fopen() uses binary mode "b" for windoze/msdog compatibility.
  19.  * v1.0   (15.04.98) phx
  20.  *        The symbol's type was wrong. It was 'Object' for absolute symbols
  21.  *        and 'Function' for reloc symbols.
  22.  *        Allocated 1 byte too less, for ".rela.xxx" strings.
  23.  * v0.9   (03.04.98) phx
  24.  *        Reloc section header was corrupted on little endian machines.
  25.  *        WEAK symbols were generated, instead of GLOBAL ones!
  26.  * v0.5   (12.10.97) phx
  27.  *        Removed "pasm V0.x" from .comment section.
  28.  * v0.3   (10.04.97) phx
  29.  *        Fixed enforcer-hit, when external references are present.
  30.  *        Some vbcc-specific changes.
  31.  *        Support for little endian architectures.
  32.  * v0.2   (25.03.97) phx
  33.  *        Writes ELF object for 32-bit PowerPC big-endian. Either absolute
  34.  *        or ELF output format may be selected. ELF is default for all
  35.  *        currently supported platforms. PPCasm supports nine different
  36.  *        relocation types (there are much more...).
  37.  *        Compiles and works also under NetBSD/amiga (68k).
  38.  *        Changed function declaration to 'new style' in all sources
  39.  *        (to avoid problems with '...' for example).
  40.  *        File created.
  41.  */
  42.  
  43.  
  44. #define OUTPUT_ELF_C
  45. #include "ppcasm.h"
  46. #include "elf.h"
  47. #include <time.h>
  48.  
  49.  
  50. struct StrTabList {
  51.   struct list l;
  52.   uint32 index;
  53. };
  54.  
  55. struct StrTabNode {
  56.   struct node n;
  57.   char *str;
  58. };
  59.  
  60. struct ShdrNode {
  61.   struct node n;
  62.   struct Elf32_Shdr s;
  63. };
  64.  
  65. struct SymbolNode {
  66.   struct node n;
  67.   char *name;
  68.   struct Elf32_Sym s;
  69. };
  70.  
  71. struct RelaNode {
  72.   struct node n;
  73.   struct Elf32_Rela r;
  74. };
  75.  
  76.  
  77. static struct Elf32_Ehdr elf_header = {
  78.   { 0x7f,'E','L','F',ELFCLASS32,0,EV_CURRENT,0,0,0,0,0,0,0,0,0 },
  79.   ECH(ET_REL),ECH(EM_POWERPC),ECW(EV_CURRENT),0,0,0,0,
  80.   ECH(sizeof(struct Elf32_Ehdr)),
  81.   0,0,ECH(sizeof(struct Elf32_Shdr)),0,0
  82. };
  83. static char *output_name;
  84.  
  85.  
  86. void output_elf32msb(struct GlobalVars *);
  87.  
  88. static struct ShdrNode *addShdr(struct list *);
  89. static struct SymbolNode *addSymbol(struct list *,struct StrTabList *,char *);
  90. static uint32 addString(struct StrTabList *,char *);
  91. static void addRela(struct list *,uint32,uint32,uint32);
  92. static void fw(FILE *,void *,size_t);
  93.  
  94.  
  95.  
  96. void output_elf32msb(struct GlobalVars *gv)
  97. {
  98.   struct list shdrlist,symlist,relalist;
  99.   struct StrTabList shstrlist,strlist;
  100.   struct ShdrNode *shn;
  101.   struct SymbolNode *sym;
  102.   uint32 symtabidx,strtabidx,shstrtabidx,firstglobal,align1,align2;
  103.   uint32 roffset=0,soffset=sizeof(struct Elf32_Ehdr);
  104.   uint32 shdrindex=0,symindex=0;
  105.   struct Section *nextsec,*sec=(struct Section *)gv->sectionlist.first;
  106.   struct Symbol *symchain;
  107.   int i;
  108.   FILE *fp;
  109.  
  110.   /* init */
  111.   output_name = gv->dest_name;
  112.   elf_header.e_ident[EI_DATA] = ELFDATA2MSB;
  113.   initlist(&shdrlist);
  114.   initlist(&symlist);
  115.   initlist(&relalist);
  116.   shstrlist.index = strlist.index = 0;
  117.   initlist(&shstrlist.l);
  118.   initlist(&strlist.l);
  119.   addString(&shstrlist,"");  /* first string is always "" */
  120.   symtabidx = addString(&shstrlist,".symtab");
  121.   strtabidx = addString(&shstrlist,".strtab");
  122.   shstrtabidx = addString(&shstrlist,".shstrtab");
  123.   addShdr(&shdrlist);  /* first Shdr is always zero */
  124.   addString(&strlist,"");
  125.   addSymbol(&symlist,NULL,NULL);  /* first symbol table entry always empty */
  126.  
  127.   /* source file name symbol */
  128.   if (gv->file) {
  129.     ++symindex;
  130.     sym = addSymbol(&symlist,&strlist,gv->file);
  131.     sym->s.st_info = ELF32_ST_INFO(STB_LOCAL,STT_FILE);
  132.     sym->s.st_shndx = ECH(SHN_ABS);
  133.   }
  134.  
  135.   /* generate section headers for program sections */
  136.   while (nextsec = (struct Section *)sec->n.next) {
  137.     if (!(sec->flags & SF_DISCARD) &&
  138.         (sec->size > 0 || (sec->flags & SF_HASSYMS))) {
  139.       sec->index = ++shdrindex;
  140.       shn = addShdr(&shdrlist);
  141.       shn->s.sh_name = ECVW(addString(&shstrlist,sec->name));
  142.       if (sec->type==ST_UDATA || (sec->flags&SF_UNINITIALIZED))
  143.         shn->s.sh_type = ECW(SHT_NOBITS);
  144.       else
  145.         shn->s.sh_type = ECW(SHT_PROGBITS);
  146.       shn->s.sh_flags = ECW(SHF_ALLOC);
  147.       if (sec->protection & SP_WRITE)
  148.         shn->s.sh_flags |= ECW(SHF_WRITE);
  149.       if (sec->protection & SP_EXEC)
  150.         shn->s.sh_flags |= ECW(SHF_EXECINSTR);
  151.       shn->s.sh_offset = ECVW(soffset);
  152.       shn->s.sh_size = ECVW(sec->size);
  153.       if (shn->s.sh_type == ECW(SHT_PROGBITS))
  154.         soffset += sec->size;
  155.       shn->s.sh_addralign = ECVW(1<<(uint32)sec->alignment);
  156.       /* add section symbol */
  157.       sym = addSymbol(&symlist,NULL,NULL);
  158.       sym->s.st_info = ELF32_ST_INFO(STB_LOCAL,STT_SECTION);
  159.       sym->s.st_shndx = ECVH((uint16)shdrindex);
  160.       ++symindex;
  161.     }
  162.     sec = nextsec;
  163.   }
  164.  
  165.   /* comment section */
  166.   if (gv->ident || gv->vc) {
  167.     ++shdrindex;
  168.     shn = addShdr(&shdrlist);
  169.     shn->s.sh_name = ECVW(addString(&shstrlist,".comment"));
  170.     shn->s.sh_type = ECW(SHT_PROGBITS);
  171.     shn->s.sh_offset = ECVW(soffset);
  172.     shn->s.sh_size = 1;  /* zero-byte */
  173.     if (gv->ident)
  174.       shn->s.sh_size += (uint32)strlen(gv->ident)+1;
  175.     if (gv->vc)
  176.       shn->s.sh_size += 12;
  177.     soffset += shn->s.sh_size;
  178. #ifdef LITTLEENDIAN
  179.     shn->s.sh_size = l2bw(shn->s.sh_size);
  180. #endif
  181.     shn->s.sh_addralign = ECW(1);
  182.     /* add section symbol */
  183.     sym = addSymbol(&symlist,NULL,NULL);
  184.     sym->s.st_info = ELF32_ST_INFO(STB_LOCAL,STT_SECTION);
  185.     sym->s.st_shndx = ECVH((uint16)shdrindex);
  186.     ++symindex;
  187.   }
  188.  
  189.   /* build symbol table */
  190.   for (i=0; i<SYMHTABSIZE; i++) {  /* first, symbols with local binding */
  191.     symchain = gv->symbols[i];
  192.     while (symchain) {
  193.       if (*(symchain->name) != '.') {  /* '.symbols' are ignored */
  194.         if (symchain->type==SYM_ABS || symchain->type==SYM_RELOC) {
  195.           if (symchain->bind == SYMB_LOCAL) {
  196.             ++symindex;
  197.             sym = addSymbol(&symlist,&strlist,symchain->name);
  198.             sym->s.st_value = ECVW(symchain->value);
  199.             sym->s.st_size = ECVW(symchain->size);
  200.             sym->s.st_info = ELF32_ST_INFO(STB_LOCAL,symchain->info);
  201.             if (symchain->type == SYM_ABS)
  202.               sym->s.st_shndx = ECH(SHN_ABS);
  203.             else
  204.               sym->s.st_shndx = ECVH((uint16)symchain->relsect->index);
  205.           }
  206.         }
  207.       }
  208.       symchain = symchain->hash_chain;
  209.     }
  210.   }
  211.   firstglobal = symindex + 1;
  212.   for (i=0; i<SYMHTABSIZE; i++) {  /* then, global and weak symbols */
  213.     symchain = gv->symbols[i];
  214.     while (symchain) {
  215.       if (*(symchain->name) != '.') {  /* '.symbols' are ignored */
  216.         if (symchain->type==SYM_ABS || symchain->type==SYM_RELOC) {
  217.           if (symchain->bind > SYMB_LOCAL) {
  218.             ++symindex;
  219.             sym = addSymbol(&symlist,&strlist,symchain->name);
  220.             sym->s.st_value = ECVW(symchain->value);
  221.             sym->s.st_size = ECVW(symchain->size);
  222.             sym->s.st_info = ELF32_ST_INFO(symchain->bind-SYMB_LOCAL,
  223.                                            symchain->info);
  224.             if (symchain->type == SYM_ABS)
  225.               sym->s.st_shndx = ECH(SHN_ABS);
  226.             else
  227.               sym->s.st_shndx = ECVH((uint16)symchain->relsect->index);
  228.           }
  229.         }
  230.       }
  231.       symchain = symchain->hash_chain;
  232.     }
  233.   }
  234.  
  235.   /* ".rela.xxx" relocation sections */
  236.   sec = (struct Section *)gv->sectionlist.first;
  237.   while (nextsec = (struct Section *)sec->n.next) {
  238.     if (!(sec->flags & SF_DISCARD) && sec->size > 0) {
  239.       struct Reloc *nextrel,*rel=(struct Reloc *)sec->reloclist.first;
  240.       struct XReference *nextxref;
  241.       struct XReference *xref=(struct XReference *)sec->xreflist.first;
  242.       uin